#include "glwidget.h"

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)
{
    setAttribute(Qt::WA_DeleteOnClose);
    drawer = OGLDrawer( );
    factory = CurveFactory< QPointF >( );

    addCurve( BezierC );
//    mouseState  = ZERO;
//    krzywa      = BezierC;
}

void GLWidget::addCurve( CurveType curveType )
{
    /* Przykladowa krzywa. */
    properties.push_back( CurveProperties( ) );

    curves.push_back( factory.CreateCurve( curveType ) );
    curves[0]->AddPoint(QPointF(100,100));
    curves[0]->AddPoint(QPointF(200,30));
    curves[0]->AddPoint(QPointF(300,120));
    curves[0]->AddPoint(QPointF(40,450));

    properties[0].SetBorders(QPointF(40,450), QPointF(300,120), QPointF(40,450), QPointF(200,30));
}

//void GLWidget::setEditedCurve( int curve )
//{
//    krzywa = curve;
//}

void GLWidget::mousePressEvent(QMouseEvent* event)
{
    /* Rzutujemy na kwadrat 500x500. */
    double x = event -> x() * 500.0 / (double)width();
    double y = (height() - event -> y()) * 500.0 / (double)height();
    selection w  = curveSelection(event -> x(), event -> y());
    QPointF point(x, y);

//    if (event -> button() == Qt::RightButton)
//    {
//        /*
//        // Zostawiam ten kod na przyszlosc;p (w razie czego).
//        QString s;
//        //QTextStream(&s) << "x = " << x << " y = " << y << "; ex = " << event->x() << " ey = " << event->y();
//        QTextStream(&s) << w.typ_krzywej << " " << w.curve_index << " " << w.control_point_index;
//        QMessageBox::about(this, tr("pozycje"), s);
//        */
//    }

//    if (event -> button() == Qt::LeftButton)
//    {
//        if ( w.curve_type != -1 && mouseState == ZERO )
//        {
//            mouseState  = MOVING;
//            moved_point = w;//curveSelection(event -> x(), event -> y());
//        }

//        else
//        {
//            switch (krzywa)
//            {

//                case CT_NURBS:
//                    nurbs_curves[0].AddControlPoint(point, 1.0);
//                    krzywa = CT_NURBS;
//                    break;

//            /*    case CT_BEZIER:
//                    bezier_curves[0].AddControlPoint(point);
//                    krzywa = CT_BEZIER;
//                    break;
//            */
//            }
//        }
//    }

    // Aktualizujemy to, co zmienielismy.
    updateGL();
}

void GLWidget::mouseMoveEvent(QMouseEvent* event)
{
//    if ( mouseState == MOVING )
//    {
//        /* Rzutujemy na kwadrat 500x500. */
//        double x = event -> x() * 500.0 / (double)width();
//        double y = (height() - event -> y()) * 500.0 / (double)height();
//        QPointF point(x, y);

//        switch ( moved_point.curve_type )
//        {
//            case CT_BEZIER:
//                //bezier_curves[moved_point.curve_index].MovePoint(moved_point.control_point_index, point);
//                break;

//            case CT_NURBS:
//                nurbs_curves[moved_point.curve_index].MovePoint(moved_point.control_point_index, point);
//                break;
//        }

//        updateGL();
//    }
}

void GLWidget::mouseReleaseEvent(QMouseEvent* event)
{
//    mouseState = ZERO;
    updateGL();
}

void GLWidget::initializeGL()
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}

void GLWidget::resizeGL(int width, int height)
{
    glViewport(0, 0, (GLint)width, (GLint)height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0, 500.0, 0.0, 500.0);
    glEnable (GL_LINE_SMOOTH);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();

    draw();

    glFlush();
}

selection GLWidget::curveSelection(int x, int y)
{
    selection w;
    const int bufferSize = 1024;
    unsigned int buffer[bufferSize];

    for (int i = 0; i < bufferSize; i++)
            buffer[i] = -1;

    glSelectBuffer(bufferSize, buffer);

    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();

    int viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    gluPickMatrix(x, viewport[3] - y, 1, 1, viewport);

    gluOrtho2D(0.0, 500.0, 0.0, 500.0);

    glMatrixMode(GL_MODELVIEW);

    glRenderMode(GL_SELECT);
    draw();

    int hits = glRenderMode(GL_RENDER);

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();

    glMatrixMode(GL_MODELVIEW);

    if (hits > 0)
    {
        int numofitems           = buffer[0];
        int index                = 0;

        for (int i = 0; i < hits; i++)
        {
                index      = 2 + numofitems;
                numofitems = buffer[index];
        }

//        QString s;
//        QTextStream(&s) << "hits = " << hits << "\n";

//        for (int i = 0; i < 20; i++)
//            QTextStream(&s) << "  buffer[" << i <<"] = " << buffer[i] << "\n";

        //QMessageBox::about(this, tr("pozycje"), s);

        w.curve_index  = buffer[index - 2];
        w.point_index  = buffer[index - 1];

        return w;
    }

    w.curve_index  = -1;
    w.point_index  = -1;

    return w;
}

void GLWidget::draw( )
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glInitNames();  // Tworzymy bufor nazw
    glPushName(-1); // Wsadzamy byle co do bufora

    for ( unsigned int i = 0; i < curves.size( ); i++ )
    {
        glPushName( i );
        drawer.DrawSelectionBox(properties[i]);
        drawer.DrawCurve( *(curves[i]), properties[i] );
        drawer.DrawControlPolyline(*(curves[i]), properties[i]);
        drawer.DrawControlPoints(*(curves[i]), properties[i]);
        glPopName( );
    }
}
